<script lang="ts" setup>
import {message} from 'ant-design-vue';

import type {IBaseRequest, IPageRequest, ISearchParams} from '@/types/request';
import type {ColumnsType, TablePaginationConfig} from 'ant-design-vue/es/table';
import type {Transform, PaginationConfig, TransformValueOf} from '@/types/table-transform';
import {uploadImage} from '@/api/upload';

const {expandColumns, realDataSource, searchParams, notDel, notGmt, ...methods} = defineProps<{
    expandColumns: ColumnsType
    realDataSource: Transform<any>[]
    searchParams: ISearchParams
    notDel?: boolean
    custom?: boolean
    notGmt?: boolean
    onRequest: () => Promise<IPageRequest<any>>
    onDelete?: (value: string) => Promise<IBaseRequest<any>>
    onUpdate?: (value: TransformValueOf<Transform<any>>) => Promise<IBaseRequest<any>>
}>()

// 默认表的列格式
const defaultColums: ColumnsType = [
    !notGmt ? {
        title: '创建时间',
        dataIndex: 'gmt_create',
        key: 'gmt_create',
        notShowInput: true,
        width: 120
    } : {},
    methods?.onUpdate ? {
        title: '操作',
        key: 'operation',
        width: 180,
        fixed: 'right'
    } : {},
]

// 分页器逻辑
const pagination = $ref<PaginationConfig>({
    title: '',
    current: 0,
    total: 0,
    pageSize: 0,
    onChange: async (page) => {
        searchParams.page = page
        await handleRequest()
    },
})

// 监听搜索内容改变分页器的数据
watch(() => searchParams, () => {
    pagination.current = searchParams.page
    pagination.total = searchParams.total
    pagination.pageSize = searchParams.size
}, {deep: true})


// 将 有原始值和修改后的值 数据更改为只有修改后的值
const dataSource = $computed(() => {
    return realDataSource.map(item => Object.entries(item).reduce((acc, [key, value]) => {
        return {
            ...acc,
            [key]: value.text
        }
    }, {}))
})

console.log(dataSource);

// 汇总表格的列格式
const columns = $computed<ColumnsType>(() => {
    return [
        {
            title: 'ID',
            dataIndex: 'id',
            key: 'id',
            notShowInput: true,
            width: 100,
            fixed: 'left'
        },
        ...expandColumns,
        ...defaultColums.filter(item => item.title),
    ]
})

// 数据改变时表格加载的动画
let isLoading = $ref(false)

async function request(callback: () => Promise<void>) {
    isLoading = true
    try {
        await callback()
    } catch (error: any) {
        message.error(error.message || error)
    } finally {
        isLoading = false
    }
}

// 执行父组件传入的搜索方法
async function handleRequest() {
    await request(async () => {
        const {data} = await methods.onRequest()
        searchParams.total = data.total_record
    })
}

// 删除方法
async function handleDelete(index: number) {
    const record = realDataSource[index]
    if (record.del.value) {
        message.error('此项目已经被删除')
        return
    }

    await request(async () => {
        if (!methods.onDelete) {
            return
        }
        const {code} = await methods.onDelete(String(record.id.value))
        if (code === 0) {
            message.success('删除成功')
            await handleRequest()
        }
    })
}

let editingIndex = $ref(-1)
let editableData = $ref<Transform<any>>()

async function handleEditOrSave(index: number) {
    // 保存逻辑
    if (editingIndex === index) {
        // 将有原始值和修改后的值 数据更改为只有原始的值
        const toUploadData = Object.entries(editableData!).map(([key, value]) => {
            return {
                [key]: value.value
            }
        }).reduce((acc, cur) => {
            return {
                ...acc,
                ...cur
            }
        }, {}) as TransformValueOf<typeof realDataSource[0]>

        await request(async () => {
            if (!methods?.onUpdate) return
            const {code} = await methods.onUpdate(toUploadData)
            if (code === 0) {
                editingIndex = -1
                message.success('修改成功')
                await handleRequest()
            }
        })
    } else {
        // 编辑逻辑
        editingIndex = index
        editableData = realDataSource[index]
    }
}

// 取消方法
function handleCancel() {
    editingIndex = -1
    editableData = undefined
}

const uploadImg = $ref<HTMLInputElement>()

// 点击上传图片
function handleUploadImageUpload() {
    uploadImg!.click()
}

let imageUploadLoading = $ref(false)

// 更新图片
async function handleUploadImageChange(index: number, columnKey: string, e: Event) {
    const target = e.target as HTMLInputElement
    const file = target.files?.[0]
    if (file) {
        imageUploadLoading = true
        const {code, data} = await uploadImage(file).finally(() => imageUploadLoading = false)
        if (code === 0) {
            realDataSource[index][columnKey].value = data
        } else {
            message.error('上传失败，请重试')
        }
    }
}

onMounted(async () => await handleRequest())
</script>

<template>
    <a-table :pagination="pagination" :columns="columns" :data-source="dataSource" :loading="isLoading">
        <template #bodyCell="{ column, record, index }">
            <!-- 输入框的列 -->
            <template v-if="editingIndex === index && column.key !== 'operation' && !column.notShowInput">
                <a-input v-model:value="editableData![column.key as any].value"/>
            </template>
            <!-- 图片的列 -->
            <template v-if="column.showImage">
                <div v-if="editingIndex === index" cursor-pointer @click="handleUploadImageUpload">
                    <input type="file" hidden ref="uploadImg"
                           @change="handleUploadImageChange(index, column.key, $event)"/>
                    <div relative w-full h-full>
                        <img :src="(editableData![column.key].value)">
                        <div absolute top="0" left="0" w="full" h="full" style="background-color: rgba(0, 0, 0, 0.5);"
                             flex="~ center">
                            <loading-outlined v-show="imageUploadLoading" class="c-white! text-5"/>
                            <plus-outlined v-show="!imageUploadLoading" class="c-white! text-5"/>
                        </div>
                    </div>
                </div>
                <img :src="record[column.key]" v-else/>
            </template>
            <!-- 插槽内容 -->
            <template v-if="custom">
                <slot :index="index" :record="record" :column="column" :editableData="editableData"
                      :editState="editingIndex === index"/>
            </template>
            <!-- 操作的列 -->
            <template v-if="column.key === 'operation' && onUpdate">
                <a-button type="primary" mr-1 @click="handleEditOrSave(index)"
                          :disabled="imageUploadLoading && editingIndex === index">
                    {{ editingIndex === index ? '保存' : '编辑' }}
                </a-button>

                <a-popconfirm title="确定要删除吗？" ok-text="确定" cancel-text="取消" @confirm="handleDelete(index)"
                              v-if="editingIndex !== index && onDelete">
                    <a-button type="primary" danger :disabled="imageUploadLoading && editingIndex === index">删除
                    </a-button>
                </a-popconfirm>
                <a-button @click="handleCancel" :disabled="imageUploadLoading && editingIndex === index"
                          v-else-if="editingIndex === index">取消
                </a-button>
            </template>
        </template>
    </a-table>
</template>

<style> .ant-table-thead > tr > th {
    text-align: center;
}

.ant-table-tbody > tr > td {
    text-align: center;
}

.truncate-cell {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
</style>
